<template>
  <section class="custom-table">
    <div class="custom-table__header" ref="customTbableHeader">
      <TableHeader
        ref="tableHeaderRef"
        :columns="columns"
        :colMinWidth="colMinWidth"
        :selection="selection"
        :disabledMove="disabledMove"
        :fixdColumns="fixdColumns"
        :isSrcoll="isSrcoll"
        @select-all="handleSelectAll"
        @sort-column="handleSortColumn"
        @resize-column="handleResizeColumn"
        @sort-change="handleSort"
        @fixed-change="handleFixed"
      />
    </div>
    <div class="custom-table__body" ref="customTbableBody">
      <TableBody
        ref="tableBodyRef"
        :columns="columns"
        :selection="selection"
        :fixdColumns="fixdColumns"
        :isSrcoll="isSrcoll"
        :data="data"
        v-bind="{ ...$attrs }"
        :row-class-name="rowClassName"
        @select="handleSelect"
        @create="handleCreate"
        @sort-row="handleSortRow"
      >
        <!-- 传递所有插槽给 TableBody -->
        <template v-for="(_, slotName) in $slots" #[slotName]="slotProps">
          <slot :name="slotName" v-bind="slotProps" />
        </template>
      </TableBody>
    </div>
  </section>
</template>
<script>
import TableHeader from './tableHeader/index.vue';
import TableBody from './tableBody/index.vue';

export default {
  name: 'CustomTable',
  components: {
    TableHeader,
    TableBody,
  },
  props: {
    columns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    data: {
      type: Array,
      default: () => {
        return [];
      },
    },
    rowClassName: {
      type: [String, Function],
      default: '',
    },
    colMinWidth: {
      type: Number,
      default: 100,
    },
    selection: {
      type: Object,
      default: () => {
        return {
          width: 50,
          visible: true,
        };
      },
    },
    disabledMove: {
      type: Array,
      default: () => {
        return [];
      },
    },
  },
  data() {
    return {
      multipleSelection: [],
      fixdColumns: {},
      isSrcoll: false,
      lastScrollTime: 0,
      throttleDelay: 200, // 节流间隔（毫秒）
    };
  },
  watch: {
    columns: {
      immediate: true,
      deep: true,
      handler(newVal) {
        // 计算固定列
        this.processColumns(newVal);
      },
    },
  },
  created() {},
  mounted() {
    // 添加滚动事件监听器
    this.$refs.customTbableBody.addEventListener('scroll', this.handleScroll);
  },
  methods: {
    handleSelectAll(bool) {
      if (bool) {
        this.data.forEach((item) => {
          this.toggleRowSelection(item);
        });
      } else {
        this.clearSelection();
      }
      this.$emit('select-all', this.multipleSelection);
    },
    handleSelect(row) {
      this.toggleRowSelection(row, row.checked);
      this.$emit('select', this.multipleSelection, row);
    },
    handleCreate() {},
    handleSortRow(newRow, oldRow, data) {
      this.$emit('sort-row', newRow, oldRow, data);
    },
    handleSortColumn(columns) {
      this.$emit('sort-column', columns);
    },
    handleSort(column) {
      this.$emit('sort-change', column);
    },
    handleFixed(column, bool) {
      this.$emit('fixed-change', column, bool);
    },
    handleResizeColumn(columns) {
      this.$emit('resize-column', columns);
    },
    toggleRowSelection(row, bool = true) {
      if (bool) {
        const ids = this.multipleSelection.map((item) => item.id);
        if (!ids.includes(row.id)) {
          this.multipleSelection.push(row);
        }
        if (this.multipleSelection.length === this.data.length) {
          this.$refs.tableHeaderRef.toggleSelection(true); // 来源为handleSelectAll时，这个多余
        }
      } else {
        this.multipleSelection = this.multipleSelection.filter((item) => item.id !== row.id);
        this.$refs.tableHeaderRef.toggleSelection(false); // 来源为handleSelectAll时，这个多余
      }
      this.$refs.tableBodyRef.toggleRowSelection(row, bool); // 来源为handleSelect时，这个多余
    },
    clearSelection() {
      this.multipleSelection = [];
      this.data.forEach((item) => {
        this.toggleRowSelection(item, false);
      });
      this.$refs.tableHeaderRef.toggleSelection(false); // 来源为handleSelectAll时，这个多余
    },
    toggleCreate(bool) {
      this.$refs.tableBodyRef.toggleCreate(bool);
    },
    handleScroll() {
      this.$refs.customTbableHeader.scrollLeft = this.$refs.customTbableBody.scrollLeft;
      this.isSrcoll = this.$refs.customTbableBody.scrollLeft > 0;

      const now = Date.now();
      if (now - this.lastScrollTime > this.throttleDelay) {
        this.lastScrollTime = now;
        // 执行滚动处理逻辑
        this.$emit('scroll-change');
      }
    },
    resetScroll() {
      this.$refs.customTbableBody.scrollLeft = 0;
    },
    processColumns(columns) {
      let index = -1;
      this.fixdColumns = {};
      columns.forEach((item, idx) => {
        if (item.fixed) {
          index = idx;
        }
      });
      if (index < 0) {
        return;
      }
      for (let idx = 0; idx < columns.length; idx++) {
        if (idx > index) {
          break;
        }
        if (idx === 0) {
          if (this.selection.visible) {
            this.fixdColumns[columns[idx].prop] = this.selection.width;
          } else {
            this.fixdColumns[columns[idx].prop] = 0;
          }
        } else {
          this.fixdColumns[columns[idx].prop] =
            Number(this.columns[idx - 1].width) + Number(this.fixdColumns[columns[idx - 1].prop]);
        }
      }
    },
  },
  // 组件销毁时移除事件监听器
  beforeDestroy() {
    if (this.$refs.customTbableBody) {
      this.$refs.customTbableBody.removeEventListener('scroll', this.handleScroll);
    }
  },
};
</script>

<style lang="scss" scoped>
.custom-table {
  height: 100%;
  max-width: 100%;
  width: auto;
  display: inline-flex;
  flex-direction: column;
  font-size: 14px;
}
.custom-table__header {
  max-width: 100%;
  width: auto;
  overflow: hidden; /* 确保表头不会超出容器 */
  color: #6e737b;
  padding-right: 5px;
}
.custom-table__body {
  max-width: 100%;
  width: auto;
  flex: 1;
  overflow: auto;
  color: #000819;
  padding-right: 5px;
}
</style>
